#include "cybertron/network/CybertronAsyncConn.hpp"
#include "cybertron/core/Log.hpp"
#include "cybertron/network/Message.hpp"

CYBERTRON_BEGIN

CybertronAsyncConn::CybertronAsyncConn()
{
	mpClient = std::make_shared<SocketTcpClient>();
	mIp.clear();
	mPort = 0;
	mState = SUBSCRIBE_DISCONNECT;
	mNoDataCounter = 0;
}

CybertronAsyncConn::~CybertronAsyncConn()
{
}

bool CybertronAsyncConn::subscribe(const std::string & ip, int port, std::uint32_t type)
{
	mIp = ip;
	mPort = port;
	mDataTypes.emplace_back(type);
	mpClient->setHandlerConnected([this]() {
		onConnected();
	});
	mpClient->setHandlerDisconnected([this]() {
		onDisconnected();
	});
	mpClient->setHandlerMessage([this](Message& msg) {
		onMessage(msg);
	});
	if (!mpClient->connectBlocked(mIp, mPort))
	{
		mpClient->close("Close for retry later");
		return false;
	}
	NodeCommon::FromAnySubscribeData subscribe;
	subscribe.add_datatypes(type);
	mpClient->send(NodeCommon::EFromAnySubscribeData, subscribe);
	return true;
}

bool CybertronAsyncConn::subscribe(const std::string& ip, int port, const std::vector<std::uint32_t>& types)
{
	mIp = ip;
	mPort = port;
	mDataTypes = types;
	mpClient->setHandlerConnected([this]() {
		onConnected();
	});
	mpClient->setHandlerDisconnected([this]() {
		onDisconnected();
	});
	mpClient->setHandlerMessage([this](Message& msg) {
		onMessage(msg);
	});
	if (!mpClient->connectBlocked(mIp, mPort))
	{
		mpClient->close("Close for retry later");
		return false;
	}
	if (types.empty()) {
		return false;
	}
	NodeCommon::FromAnySubscribeData subscribe;
	for (auto type : types) {
		subscribe.add_datatypes(type);
	}
	mpClient->send(NodeCommon::EFromAnySubscribeData, subscribe);
	return true;
}

void CybertronAsyncConn::onTimer()
{
    mNoDataCounter++;
	mpClient->onTimer();
	if(mNoDataCounter > 100)
	{
	    logEvent("CybertronAsyncConn receive no data after 100 loop, close this connection");
	    mNoDataCounter = 0;
	    release();
	}
}

void CybertronAsyncConn::release()
{
	mpClient->close("Close on as required");
	mState = SUBSCRIBE_DISCONNECT;
}

void CybertronAsyncConn::onConnected()
{
	mState = SUBSCRIBE_CONNECT;
}

void CybertronAsyncConn::onDisconnected()
{
	mState = SUBSCRIBE_DISCONNECT;
}

void CybertronAsyncConn::onMessage(cybertron::Message& msg)
{
    mNoDataCounter = 0;
	if (mFuncOnSubscribeMsg == nullptr)
	{
		logEvent("CybertronAsyncConn no subscirbeMsg handler");
		return;
	}
	mFuncOnSubscribeMsg(msg);
}

CYBERTRON_END